<?php
/**
 * I-Cafe framework
 * 
 * @category CF
 * @package CF_Db
 * @link http://www.i-cafe.org
 * @license http://www.i-cafe.org/license
 * @version 04-04-2010
 * @author tcl_java@yahoo.com
 */

/**
 * A class perfomance for build and execute query DELETE
 * <code>
 * 	$delete = new CF_Db_Delete();
 * 	$delete->table("products")
 * 		->where("id IN(%s)", implode(",", array(1,2,3)));
 * 	echo $delete; // output: "DELETE FROM `products` WHERE id IN(1,2,3)"
 * </code>
 */
class CF_Db_Delete extends CF_Component implements CF_Db_Query_Interface
{
	/**
	 * @var string|array
	 */
	protected $_table;
	
	/**
	 * @var array
	 */
	protected $_where;
	
	/**
	 * @var array
	 */
	protected $_order;
	
	/**
	 * @var string
	 */
	protected $_limit;
	
	/**
	 * 
	 */
	public function __construct()
	{
		# notify before construct event
		$this->fireEvent('beforeconstruct', array($this));
		
		# register events
		$this->addEvents(
			'beforebuilquery',
			'buildquery',
			'beforeexecute',
			'execute'
		);
		
		$this->reset();
		
		# notify construct event
		$this->fireEvent('construct', array($this));
	}
	
	/**
	 * 
	 */
	public function reset()
	{
		$this->_table = null;
		$this->_where = array('WHERE 1');
		$this->_order = array();
		$this->_limit = null;
	}
	
	/**
	 * 
	 * @param string|array|CF_Db_Expr $table
	 * @return CF_Db_Update this
	 */
	public function table($table)
	{
		$this->_table = $table;
		return $this;
	}
	
	/**
	 * 
	 * @param string|CF_Db_Expr $cond
	 * @param mixed $values [optional]
	 * @return CF_Db_Update this
	 */
	public function where($cond, $values = null)
	{
		$this->_where[] = CF_Db_QueryPart::where($cond, $values);
		return $this;
	}
	
	/**
	 * 
	 * @param string|CF_Db_Expr $cond
	 * @param mixed $values [optional]
	 * @return 
	 */
	public function orWhere($cond, $values = null)
	{
		$this->_where[] = CF_Db_QueryPart::orWhere($cond, $values);
		return $this;
	}
	
	/**
	 * 
	 * @param string|array $columns
	 * @param string $direction [optional]
	 * @return CF_Db_Update this
	 */
	public function order($columns, $direction = null)
	{
		$this->_order[] = CF_Db_QueryPart::order($columns, $direction);
		return $this;
	}
	
	/**
	 * 
	 * @param int $count
	 * @param int $offset [optional]
	 * @return CF_Db_Update this
	 */
	public function limit($count, $offset = null)
	{
		$this->_limit = CF_Db_QueryPart::limit($count, $offset);
		return $this;
	}
	
	/**
	 * Execute UPDATE query
	 * @return int
	 */
	public function execute()
	{
		$query = $this->__toString();
		
		# notify before execute event
		if(CF_Observable::VALUE_RETURN === $this->fireEvent('beforeexecute', array($this, &$query))) return;
		
		CF_Db::getInstance()->query($query);
		$res = CF_Db::getInstance()->getAfftectedRows();
		
		# notify execute event
		$this->fireEvent('execute', array($this, &$res, &$query));
		return $res;
	}
	
	/**
	 * Build query update
	 * @return string
	 */
	public function __toString()
	{
		# notify before build query event
		if(CF_Observable::VALUE_RETURN === $this->fireEvent('beforebuilquery', array($this))) return;
		$parts = array();
		$parts[] = 'DELETE FROM';
		
		# render table
		$parts[] = ($this->_table instanceof CF_Db_Expr)?
					(string) $this->_table
					: CF_Db::getInstance()->quoteIdentifier($this->_table);
					
		# render where
		if($this->_where){
			$parts[] = implode(' ', $this->_where);
		}
		
		# render order
		if($this->_order){
			$parts[] = 'ORDER BY ' . implode(',', $this->_order);
		}
		
		# render limit
		if($this->_limit){
			$parts[] = $this->_limit;
		}
		
		$query = implode(' ', $parts);
		
		# notify build query event
		$this->fireEvent('buildquery', array($this, &$query));
		
		return $query;
	}
}
